package com.midou.administration.service.impl;

import com.midou.administration.bo.Msg;
import com.midou.administration.entity.Coupon;
import com.midou.administration.entity.UserCoupon;
import com.midou.administration.service.CouponService;
import com.midou.administration.service.RedisService;
import com.midou.administration.service.UserCouponService;
import com.netflix.discovery.converters.Auto;
import org.checkerframework.checker.units.qual.A;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.scripting.support.ResourceScriptSource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.File;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;

@Service
public class RedisServiceImpl implements RedisService {

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    /**
     * 用户卡包表的接口对象
     */
    @Autowired
    private UserCouponService userCouponService;

    @Autowired
    private RedisService RedisService;

    @Autowired
    private CouponService couponService;


    private DefaultRedisScript<String> redisScript =  new DefaultRedisScript<>();

    /**
     * 判断是否抢购成功
     * @param userCoupon  用户id  优惠券id
     * @return  是否抢购成功
     */
    @Override
    @Transactional
    public Msg getResule(UserCoupon userCoupon) {

        /* 指定录取脚本路径                 资源脚本路径               加载指定资源文件 */
        redisScript.setScriptSource(new ResourceScriptSource(new ClassPathResource(File.separator+"redis"+ File.separator+"test.lua")));
        redisScript.setResultType(String.class);        //返回值是String 类型
        List<String> list = new ArrayList<>();          //定义key的集合
        list.add("seckill:stock:"+userCoupon.getUcCpId());            //传入key值的集合 args就是 参数列表
        String str =  stringRedisTemplate.execute(redisScript,list,""+1);    //执行lua命令 获取返回结果

        System.out.println("抢购结果是:"+str);

        //重新计算TTL
        this.reset(userCoupon.getUcCpId());

        System.out.println("重新计算TTL");
        if("SUCCESS".equals(str)){
            userCoupon.setUcState(1);
            this.RedisService.addRedisSet(userCoupon.getUcCpId(),userCoupon.getUcUserId());
            /**
             * 向卡包表添加一条记录  该状态在上 已经赋值过了   为:1
             */
            Integer count = this.userCouponService.createNew(userCoupon);
            if(count <= 0){
                System.out.println("有问题!请联系管理员");
            }
            /**
             * 进行减库存操作
             * 传入的是活动的id
             */
            this.couponService.updateKucun(userCoupon.getUcCpId());

            return new Msg(true,"抢购成功");
        }
        return new Msg(false,"再接再励!祝您好运连连!");
    }

    /**
     * 判断该用户是否抢购过该商品
     * @param cpId  商品id
     * @param userId    用户id
     * @return  是否抢购过
     */
    @Override
    public Boolean Redo(Integer cpId, Integer userId) {
        Boolean b;
        try {
             b = this.stringRedisTemplate.opsForSet().isMember("activity:" + cpId, userId.toString());
        }catch (Exception e){
            return false;
        }
       return b;
    }

    @Override
    public void addRedisSet(Integer cpId, Integer userId) {
        this.stringRedisTemplate.opsForSet().add("activity:"+cpId,userId.toString());
    }

    @Override
    public String getAuthCode(String phone) {
        String result = this.stringRedisTemplate.opsForValue().get(phone);
        return result;
    }

    @Override
    public void reset(int code) {
        //开始时间戳 - 当前时间戳    +   结束时间戳 - 开始时间戳

        Coupon c = this.couponService.selectByid(code);
        long time = zh(c.getCpBeginTime()) - zh(new Date()) + zh(c.getCpEndTime()) - zh(c.getCpBeginTime());

        //放入到redis当中是 并设置过期时间
        time = time - 5;
        this.stringRedisTemplate.expire("seckill:stock:"+code,time, TimeUnit.SECONDS);
    }

    /**
     * 计算时间戳
     * @param date 要计算的时间
     * @return  long时间戳
     */
    public long zh(Date date){
        long ts = date.getTime();
        ts = ts/1000;
        return ts;
    }
}
